/**
 * 导入vite模块
 */
import { defineConfig, loadEnv } from 'vite';

/**
 * 导入vite插件
 */
import vue from '@vitejs/plugin-vue';
import legacy from '@vitejs/plugin-legacy'; // 是 Vite 提供的一个插件，用于为传统浏览器提供向后兼容性支持
import AutoImport from 'unplugin-auto-import/vite'; // unplugin-auto-import/vite是一个Vite插件，用于自动导入Vue、Vue Router、Pinia等常用库的API，从而减少手动导入的工作量，提高开发效率
import Components from 'unplugin-vue-components/vite'; // unplugin-vue-components/vite是一个Vite插件，用于自动导入Vue组件，从而减少手动导入的工作量，提高开发效率
import viteCompression from 'vite-plugin-compression'; // 是一个Vite插件，用于压缩打包后的文件，从而减小文件大小，提高加载速度
import autoprefixer from 'autoprefixer'; // 是一个PostCSS插件，用于自动添加浏览器前缀

/**
 * 导入elementplus的解析器
 */
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';

/**
 * 导入node模块, 例如：resolve, 例如：resolve(__dirname, './')，表示当前目录下的dist文件夹
 */
import { resolve } from 'path';

/**
 * 导入类型声明, 例如：ConfigEnv, 例如：UserConfig
 */
import type { ConfigEnv, UserConfig } from 'vite';

import UnoCSS from 'unocss/vite'

/**
 * 导出vite配置，导出一个默认的模块成员，
 * 该成员是一个函数，接受一个参数env，该参数是ConfigEnv类型的对象，
 * 返回一个UserConfig类型的对象
 */
export default defineConfig((env: ConfigEnv) => {
  /**
   * 获取当前时间戳
   */
  const timestamp: number = new Date().getTime();

  /**
   * 获取环境变量信息 Record<string, string>，表示一个键值对的集合，其中键和值都是字符串类型
   */
  const envConfig: Record<string, string> = loadEnv(env.mode, resolve(process.cwd()));

  /**
   * 打印当前环境变量
   */
  console.log(`当前vite运行环境: ${envConfig.VITE_NODE_ENV}`);
  console.log(`当前环境变量: ${envConfig.VITE_ENV}`);
  console.log(`当前环境变量-env.mode: ${env.mode}`);


  /**
   * 配置信息
   */
  const config: UserConfig = {
    /**
     * 环境变量目录，默认为项目根目录下的 .env 文件，可以通过设置envDir选项来指定其他环境变量文件的路径
     * ，例如：envDir: './env'，表示环境变量文件的路径为项目根目录下的env文件夹下的.env文件
     * resolve(process.cwd(), './')这部分代码使用了Node.js的resolve函数来获取当前工作目录（process.cwd()）
     */
    envDir: resolve(process.cwd(), './'),

    /**
     * 静态资源服务的文件夹，默认为项目根目录下的public文件夹，可以通过设置publicDir选项来指定其他静态资源文件夹的路径，
     * 例如：publicDir: './static'，表示静态资源文件夹的路径为项目根目录下的static文件夹
     * Vite会将这个目录下的文件直接复制到构建输出目录中，并且这些文件会被视为项目的根目录
     */
    publicDir: resolve(process.cwd(), './public'),

    /**
     * 基地址,默认为'/'，表示项目的根路径，可以通过设置base选项来指定其他的基地址，
     * base: './' 表示项目的所有静态资源都将相对于当前目录进行引用
     * base: './base/' 表示项目的所有静态资源都将相对于当前目录下的base文件夹进行引用，
     * 在部署项目时，您需要确保服务器上有一个名为 base 的目录
     */
    base: './',

    /**
     * 设置别名,可以通过设置resolve.alias选项来指定其他的别名，
     */
    resolve: {
      alias: {
        // process.cwd()回当前工作目录 __dirname 返回当前模块文件所在的目录的路径
        // vite.config.ts在根目录下，所以没有区别
        '@': resolve(process.cwd(), './src'), // alias 用于设置模块路径的别名，使得在导入模块时可以使用更短或更直观的路径。
      },
      extensions: ['.vue', '.js', '.scss', '.css', '.mjs', '.ts'], // 用于配置在导入模块时可以省略的文件扩展名。
    },

    /**
     * scss配置，可以通过设置css.preprocessorOptions选项来指定其他的scss配置，
     */
    css: {
      preprocessorOptions: {
        scss: { // 选项用于配置SCSS预处理器。
          // @use 是Sass的模块系统的一部分，用于引入Sass模块，它在局部作用域中生效，对性能的影响较小。
          //  选项允许你在每个SCSS文件的顶部自动注入一些共享的SCSS代码，
          additionalData: `@use '@/assets/element-plus/index.scss' as *;`, 
        },
      },
      // 配置PostCSS插件
      postcss: {
        // 选项用于配置PostCSS插件。
        plugins: [autoprefixer()], // 是一个PostCSS插件，它会自动为CSS属性添加浏览器前缀，以确保样式在不同浏览器中的兼容性。
      },
    },

    /**
     * 插件
     */
    plugins: [
      /**
       * vue插件 
       */
      vue(),
      /**
       * unocss插件
       */
      UnoCSS({
        hmrTopLevelAwait: false,
      }),
      /**
       * 兼容性插件
       */
      legacy({
        // 支持的浏览器版本范围
        targets: [
          '> 1%, last 1 version, ie >= 11',
          'safari >= 10',
          'Android > 39',
          'Chrome >= 60',
          'Safari >= 10.1',
          'iOS >= 10.3',
          'Firefox >= 54',
          'Edge >= 15',
        ],
        additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
        polyfills: ['es.promise.finally', 'es/map', 'es/set', 'es.object.from-entries'],
        modernPolyfills: true,
        renderLegacyChunks: true,
      }),

      /**
       * 自动导入模块，也就是函数api，可以自动导入模块，不需要手动导入，可以减少代码量，提高开发效率
       */
      AutoImport({
        // 指定自动导入vue, vue-router, pinia相关的模块到auto-imports.d.ts
        // 是一个 Vue Composition API 的实用工具集，它提供了许多常用的 Vue 3 工具函数和组合式函数
        imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'],
        // 配置解析器，这里使用了ElementPlusResolver来解析Element Plus组件库的自动导入。
        resolvers: [
          ElementPlusResolver({
            importStyle: 'sass',
          }),
        ],
        // 指定生成的类型声明文件的路径，这里是项目根目录下的auto-imports.d.ts。
        // 使得 TypeScript 能够正确识别这些自动导入的 API。
        // 在TypeScript项目中，使用unplugin-auto-import插件可以自动导入一些常用的API，
        // 例如vue、vue-router、pinia等。为了让TypeScript能够正确识别这些自动导入的API，
        // 需要生成一个声明文件（d.ts），
        // 这个声明文件会告诉TypeScript哪些API是可以自动导入的。
        dts: resolve(process.cwd(), './auto-imports.d.ts'),
      }),

      /**
       * 配置组件库
       */
      Components({
        // 指定要自动导入的组件目录
        dirs: [
          resolve(process.cwd(), './src/components'),
          resolve(process.cwd(), './src/views/dashboard/components'),
        ],
        // 配置解析器，这里使用了ElementPlusResolver来解析Element Plus组件库的自动导入。
        resolvers: [
          ElementPlusResolver({
            importStyle: 'sass',
          }),
        ],
        // 指定生成的类型声明文件的路径， 会自动生成，这里是项目根目录下的components.d.ts。
        dts: resolve(process.cwd(), './components.d.ts'),
      }),

      /**
       * 开启gzip压缩
       */
      viteCompression({
        verbose: true,
        disable: false,
        threshold: 10240,
        algorithm: 'gzip',
        ext: '.gz',
      }),
    ],

    /**
     * 服务配置 可以配置代理，端口号等，可以配置跨域等
     */
    server: {
      /**
       * 端口号
       */
      port: 8082,

      /**
       * 热更新
       */
      hmr: true,
      // proxy: env.mode === "production" ? {} :{
      //   // 配置代理 代理配置通常用于开发环境
      //   '/api': {
      //     target: 'http://t.weather.itboy.net/api',//target: 'http://localhost:8080', // 目标服务器地址
      //     changeOrigin: true, // 是否改变请求源
      //     rewrite: (path) => path.replace(/^\/api/, '') // 路径重写
      //   }
      // }
    },

    /**
     * 打包配置
     */
    build: {
      /**
       * 打包前清空dist目录
       */
      emptyOutDir: true,

      /**
       * 输出目录
       */
      outDir: resolve(process.cwd(), './dist'),

      /**
       * 打包文件超出预警
       */
      chunkSizeWarningLimit: 1500,

      /**
       * rollup配置
       */
      rollupOptions: {
        // 输出
        output: {
          // 引入文件名的名称
          chunkFileNames: `js/[name]-[hash]${timestamp}.js`,
          // 包的入口文件名称
          entryFileNames: `js/[name]-[hash]${timestamp}.js`,
          // 资源文件像 字体，图片等
          assetFileNames: `assets/[ext]/[name]-[hash]${timestamp}.[ext]`,
          // 配置代码分割
          manualChunks(id) {
            if (id.includes('node_modules')) {
              return id.toString().split('node_modules/')[1].split('/')[0].toString();
            }
          },
        },
      },
    },
  };

  /**
   * 导出配置
   */
  return config;
});
